from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.edge.service import Service
from selenium.common.exceptions import TimeoutException, WebDriverException
import time
import os
import subprocess
import winreg  # 添加注册表模块
import requests  # 添加下载模块
import zipfile  # 添加解压模块
import shutil  # 添加文件操作模块
import platform  # 添加系统信息模块
import pyautogui
pyautogui.PAUSE = 0.1
pyautogui.FAILSAFE = True

# ===== 新增：自动下载EdgeDriver的函数 =====
def get_edge_version():
    try:
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Edge\BLBeacon")
        version, _ = winreg.QueryValueEx(key, "version")
        winreg.CloseKey(key)
        return version
    except Exception:
        return None

def download_edgedriver(version):
    # 获取系统位数
    arch = "win64" if platform.machine().endswith('64') else "win32"
    url = f"https://msedgedriver.azureedge.net/{version}/edgedriver_{arch}.zip"
    
    # 创建驱动程序目录
    driver_dir = os.path.join(os.path.expanduser("~"), "auto_edgedriver")
    os.makedirs(driver_dir, exist_ok=True)
    
    # 下载驱动
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        zip_path = os.path.join(driver_dir, "edgedriver.zip")
        with open(zip_path, "wb") as f:
            f.write(response.content)
        
        # 解压文件
        with zipfile.ZipFile(zip_path, 'r') as zip_ref:
            zip_ref.extractall(driver_dir)
        
        # 清理zip文件
        os.remove(zip_path)
        
        # 返回驱动路径
        return os.path.join(driver_dir, "msedgedriver.exe")
    return None

def auto_get_edgedriver_path():
    # 获取浏览器版本
    edge_version = get_edge_version()
    if not edge_version:
        raise Exception("无法获取Edge浏览器版本")
    
    # 检查是否已有匹配版本的驱动
    driver_dir = os.path.join(os.path.expanduser("~"), "auto_edgedriver")
    driver_path = os.path.join(driver_dir, "msedgedriver.exe")
    
    # 如果驱动不存在或版本不匹配则下载
    if not os.path.exists(driver_path):
        return download_edgedriver(edge_version)
    return driver_path

# ===== 主程序开始 =====
user_data_dir = os.path.expanduser("~") + r"\AppData\Local\Microsoft\Edge\User Data"
profile_dir = "Default"

# 自动获取EdgeDriver路径
try:
    edge_driver_path = auto_get_edgedriver_path()
    print(f"使用自动下载的EdgeDriver: {edge_driver_path}")
except Exception as e:
    print(f"自动下载失败: {e}")
    # 失败时使用备选路径
    edge_driver_path = r"C:\Users\Devin\.cache\selenium\msedgedriver\win64\136.0.3240.47\msedgedriver.exe"
    print(f"使用备选路径: {edge_driver_path}")

def clean_browser_resources():
    try:
        subprocess.run(["taskkill", "/F", "/IM", "msedge.exe"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        print("已清理浏览器残留进程")
    except Exception as e:
        print(f"清理浏览器资源时出错: {e}")

clean_browser_resources()

options = webdriver.EdgeOptions()
options.add_argument(f"--user-data-dir={user_data_dir}")
options.add_argument(f"--profile-directory={profile_dir}")

service = Service(executable_path=edge_driver_path)
driver = webdriver.Edge(service=service, options=options)
wait = WebDriverWait(driver, 1)
driver.maximize_window()
# 访问抖音个人主页
driver.get("https://www.douyin.com/user/self")

try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, 'RlLOO79h'))
    )
    print("登录状态已继承")
except:
    print("未能继承登录状态，请检查用户数据目录配置")


try:
    like_Tab = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, '#semiTablike'))
    )
    like_Tab.click()
except:
    print("未能找到点赞选项卡，启用盲点模式，请确保元素无遮挡")
    pyautogui.click(618, 460, duration=0.01)
try:
    user_detail_elements = wait.until(
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, "li.SmHs0qqX.Q_uOVQ1u.SBWUpJd_"))
    )
    first_element = user_detail_elements[0]
    first_element.click()
except Exception as e:
    print(f"定位第一个视频失败: {e}，改用盲点")
    pyautogui.click(618, 666, duration=0.01)
try:
    comment_count = wait.until(
        EC.presence_of_element_located((By.CSS_SELECTOR, '#sliderVideo > div.UsWJJZhB.playerContainer.hide-animation-if-not-suport-gpu.jjWFxVjy > div > div > div.MarSXdLE.YmptQEz6.nRO8QGrO.ZIb5PiHy.positionBox > div.jkfSVWLT > div:nth-child(3) > div > div.SfwAcdr1.JrV13Yco'))
    )
    comment_count.click()
    time.sleep(1)
    comment = driver.find_element(By.ID, "semiTabcomment")  # 根据 id 检测评论区是否打开
    print(f"{comment.text} 已打开,评论数：{comment_count.text}")
except Exception as e:
    print(f"定位评论按钮失败: {e}，改用盲点")
    pyautogui.click(2500, 866, duration=0.01)
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.scroll_by_amount(0, -300).perform()  # 向上滚动300像素 [5,8](@ref)
autoplay_button = wait.until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "xg-icon.xgplayer-autoplay-setting.automatic-continuous"))
)
actions.move_to_element(autoplay_button).perform()
autoplay_tip = wait.until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "xg-icon.xgplayer-autoplay-setting.automatic-continuous > div.xgTips"))
)
shortcutKey_text = autoplay_tip.text.split('\n')
first_line_tip = shortcutKey_text[0]
if first_line_tip == "关闭自动连播":
    autoplay_button.click()
    print("连播已开启，执行了关闭操作")
else:
    print(f"当前连播提示为：{first_line_tip}，无需操作")


# 不断地使 “加载中” 的提示出现在视口中，模拟人工滚动，直到页面底部没有更多评论提示，或者页面底部提示：“暂时没有更多评论”
loading_tip = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, 'div.ETuXBjRi'))
)
loop_count = 0
# 最大循环次数已注释，调试时可取消注释以便快速测试
#max_loops = 6
#while loop_count < max_loops:
while True:
    try:
        bottom_tip = WebDriverWait(driver, 1).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "div.cnqD49jq"))
        )
        break
    except TimeoutException:
        driver.execute_script(
            "arguments[0].scrollIntoView({block: 'nearest', behavior: 'smooth'});",
            loading_tip
        )
        loop_count += 1
        print(f"检测到未到达页面底部：{loading_tip.text}, 第{loop_count}次尝试滚动")
        print(f"第{loop_count}次尝试")
bottom_tip.click()
print(f"检测到提示：{bottom_tip.text}")
# 获取并持久化评论列表
import csv

# 等待评论项加载完成
comment_items = WebDriverWait(driver, 10).until(
    EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'div[data-e2e="comment-item"]'))
)

records = []
seen_usernames = set()

for item in comment_items:
    # 1. 用户名
    try:
        username = item.find_element(
            By.CSS_SELECTOR, 'a[href*="/user/"] span span span span span span span'
        ).text.strip()
    except Exception:
        continue

    if username in seen_usernames:
        continue
    seen_usernames.add(username)

    # 2. 用户主页链接
    try:
        user_link = item.find_element(
            By.CSS_SELECTOR, 'a[href*="/user/"]'
        ).get_attribute('href')
    except Exception:
        user_link = ""

    # 3. 时间与位置
    try:
        time_location = item.find_element(
            By.CSS_SELECTOR, 'div.fJhvAqos span'
        ).text
        location = time_location.split('·')[-1].strip()
    except Exception:
        location = ""
        time_location = ""

    # 4. 标签检测（作者、你的关注等）
    tags = item.find_elements(By.CSS_SELECTOR, 'span.comment-item-tag-text')
    remark = ""
    for tag in tags:
        tag_text = tag.text.strip()
        if tag_text:           # 有内容才写入
            remark = tag_text
            break              # 只取第一个有效标签

    # 5. 组装数据
    records.append({
        'username': username,
        'location': location,
        'following_count': "",
        'follower_count': "",
        'follow_btn_status': "unknown",
        'status': f"{username}_未处理",
        'remark': remark,
        'user_link': user_link
    })

# 将数据写入CSV文件
print(f"共发现{len(records)}条有效评论数据，开始写入CSV文件")
with open('comments.csv', mode='w', newline='', encoding='utf-8') as file:
    if records:  # 确保records列表不为空
        writer = csv.DictWriter(file, fieldnames=records[0].keys())
        writer.writeheader()
        writer.writerows(records)
        print("评论数据已成功写入CSV文件，且已去重")
    else:
        print("没有找到有效的评论数据")



input("\n按回车键退出...")
driver.quit()